#include "GameState.h"

GameState* GameState::gameState = 0;

GameState::GameState(sf::RenderWindow* window, sfge::StateManager* mgr) : sfge::State(window, mgr), newLevel(false), accumulator(0), totalTime(0), currentLvl(0)
{

}

GameState::~GameState()
{

}

void GameState::init()
{
    window->ShowMouseCursor(false);
    if(spaceBackground)
        background.SetTexture(rm->getTexture("stars.png"));
    else
        background.SetTexture(rm->getTexture("gameBackground.png"));
    infoBackground.SetTexture(rm->getTexture("infoBackground.png"));
    infoBackground.SetPosition(800, 0);
    rm->getTexture("explosion6.png");

    scoreText.SetString("Score: 0");
    scoreText.SetCharacterSize(15);
    scoreText.SetPosition(830, 100);
    scoreText.SetFont(font);

    playTimeClock.Start();

    loadLevels();

    heart.SetTexture(rm->getTexture("Heart.png"));
    pauseSprite.SetTexture(rm->getTexture("pauseBonus.png"));
}

void GameState::cleanup()
{
    reset();
    saveStats();
    resetStats();
}

void GameState::saveStats()
{
    int time;
    int livesLost;
    int highscore;
    std::ifstream file;
    std::string buffer;
    file.open("Data/stats.txt");

    int brickscores[5] = {0,0,0,0,0};
    int bonusscores[6] = {0,0,0,0,0,0};

    for(int i = 0; i < 5; i++)
        file >> brickscores[i];
    for(int i = 0; i < 6; i++)
        file >> bonusscores[i];
    file >> time;
    file >> highscore;
    if(highscore < tBestScore)
        highscore = tBestScore;

    //uuggllyy
    brickscores[0] += tNormalBricks;
    brickscores[1] += tExploBricks;
    brickscores[2] += tGreenBricks;
    brickscores[3] += tMiniBricks;
    brickscores[4] += tPinBricks;

    bonusscores[0] += tBiggerPanelBonuses;
    bonusscores[1] += tSmallerPanelBonuses;
    bonusscores[2] += tLiveBonuses;
    bonusscores[3] += tPauseBonuses;
    bonusscores[4] += tAcidBonuses;
    bonusscores[5] += tBallBonuses;

    livesLost += tLivesLost;



    file.close();
    std::ofstream outfile;
    outfile.open("Data/stats.txt");
    for(int i = 0; i < 5; i++)
        outfile << brickscores[i]<<" ";
    for(int i = 0; i < 6; i++)
        outfile << bonusscores[i]<<" ";
    outfile << time + static_cast<int>(playTimeClock.GetElapsedTime().AsSeconds()) << " ";
    outfile << highscore;
    outfile.close();
}

void GameState::resetStats()
{
    tNormalBricks = 0;
    tExploBricks = 0;
    tGreenBricks = 0;
    tMiniBricks = 0;
    tPinBricks = 0;
    tBiggerPanelBonuses = 0;
    tSmallerPanelBonuses = 0;
    tLiveBonuses = 0;
    tPauseBonuses = 0;
    tAcidBonuses = 0;
    tBallBonuses = 0;
    tLivesLost = 0;
    tBestScore = 0;
}

void GameState::update()
{
    updateText();
    accumulator += clock.GetElapsedTime().AsMilliseconds();
    clock.Reset(true);
    while(accumulator > TIMESTEP)
    {
        float x = sf::Mouse::GetPosition(*window).x;
        x = window->ConvertCoords(x, 3).x;
        levels[currentLvl]->update(x);
        accumulator -= TIMESTEP;
    }

    if(levels[currentLvl]->levelComplete) //level over
    {
        currentLvl++;
        newLevel = true;
        Pause = true;
    }

    if(lives == 0) //G A M E   O V E R
    {
        reset();
        stateManager->pushState(GameoverState::Instance(window, stateManager));
        return;
    }
}

void GameState::reset()
{
    currentLvl = 0;
    points = 0;
    lives = 3;
    pauseCount = 0;
    for(auto itr = levels.begin(); itr != levels.end(); itr++)
    {
        delete (*itr);
    }
    levels.clear();
    loadLevels();
}

void GameState::loadLevels()
{
    Level* l1 = new Level("Data/Levels/l1.xml");
    levels.push_back(l1);
    Level* l2 = new Level("Data/Levels/l2.xml");
    levels.push_back(l2);
    Level* l3 = new Level("Data/Levels/l3.xml");
    levels.push_back(l3);
    Level* l4 = new Level("Data/Levels/l4.xml");
    levels.push_back(l4);
    Level* l5 = new Level("Data/Levels/l5.xml");
    levels.push_back(l5);
    Level* l6 = new Level("Data/Levels/l6.xml");
    levels.push_back(l6);
    Level* l7 = new Level("Data/Levels/l7.xml");
    levels.push_back(l7);
    Level* l8 = new Level("Data/Levels/l8.xml");
    levels.push_back(l8);
}

void GameState::updateText()
{
    scoreText.SetString("Score: " + to_string(points));
}

void GameState::handle()
{
    sf::Event Event;
    while (window->PollEvent(Event))
    {
        switch (Event.Type)
        {
            case sf::Event::Closed:
                window->Close();
                break;
            case sf::Event::KeyPressed:
            {
                if(Event.Key.Code == sf::Keyboard::D)
                {
                    devConsole.enabled = !devConsole.enabled;
                }
                if(Event.Key.Code == sf::Keyboard::Escape)
                {
                    stateManager->popState();
                    return;
                }
                if(Event.Key.Code == sf::Keyboard::Space)
                {
                    levels[currentLvl]->addBall();
                }
                break;
            }
            case sf::Event::MouseButtonPressed:
            {
                if(Event.MouseButton.Button == sf::Mouse::Left)
                    levels[currentLvl]->mousePressed();
            }
            break;
            default: break;
        }
    }
}


void GameState::draw()
{
    window->Draw(background);
    levels[currentLvl]->draw(window);
    window->Draw(infoBackground);
    window->Draw(scoreText);
    heart.SetPosition(830, 150);
    for(int i = 0; i < lives; i++)
    {
        heart.SetPosition(830 + i * 35, 150);
        window->Draw(heart);
    }
    for(int i = 0; i < pauseCount; i++)
    {
        pauseSprite.SetPosition(830 + i * 35, 200);
        window->Draw(pauseSprite);
    }

    devConsole.draw(levels[currentLvl], window);
    window->Display();
}

DevConsole::DevConsole() : enabled(false)
{
    bricksText.SetCharacterSize(10);
    bonusesText.SetCharacterSize(10);
    fpsText.SetCharacterSize(10);
    ballText.SetCharacterSize(10);
    bricksText.SetPosition(840, 500);
    bonusesText.SetPosition(840, 520);
    fpsText.SetPosition(840, 560);
    ballText.SetPosition(840, 540);
    frameClock.Restart();
}

void DevConsole::draw(Level* level, sf::RenderWindow* window)
{
    if(enabled)
    {
        bricksText.SetString("Bricks: " + to_string(level->bricks.size()));
        ballText.SetString("Balls: " + to_string(level->balls.size()));
        bonusesText.SetString("Bonuses: " + to_string(level->bonuses.size()));
        unsigned frameTime = frameClock.GetElapsedTime().AsMilliseconds();
        if(frameTime != 0)
        {
            unsigned i = 1000/frameTime;
            fpsText.SetString("FPS: " + to_string(i));
        }
        window->Draw(bricksText);
        window->Draw(bonusesText);
        window->Draw(ballText);
        window->Draw(fpsText);
    }
    frameClock.Restart();
}
